package com.peoit.honeycomb.domain.repository;

import com.peoit.honeycomb.domain.BaseEntity;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by Bing.Zeng on 2015/9/23.
 */

@Repository
public class HibernateEntityRepository implements EntityRepository {

     @PersistenceContext
     private EntityManager entityManager;
     @Override
     @Transactional
     public <T extends BaseEntity> T create(T entity) {
         entityManager.persist(entity);
         return entity;
    }

    @Override

    public <T extends BaseEntity> void update(T entity) {
        entityManager.merge(entity);
    }

    @Override
    public <T extends BaseEntity> void delete(Class<T> entityClass, Object id) {

    }

    @Override
    public <T extends BaseEntity> T find(Class<T> entityClass, Object entityId) {
        return entityManager.find(entityClass,entityId);
    }


    @Override
    public <T extends BaseEntity>  T queryByWhereSingle(Class<T> entityClass, String whereSql, Object[] queryParams) {
         String entityClassName = entityClass.getName();
        Query query = entityManager.createQuery(
                "SELECT o FROM "
                        + entityClassName
                        + " o "
                        + ((whereSql == null || whereSql.length() == 0) ? ""
                        : "WHERE " + whereSql));
        setQueryParams(query, queryParams);
        query.setHint("org.hibernate.cacheable", true);
        //查询第一条数据
        query.setMaxResults(1);
        List<T> list =  query.getResultList() ;
        if(list.size()>0) {
            return list.get(0);
        } else {
           return null;
        }
    }

    @Override
    public <T extends BaseEntity> List<T> queryByWhereList(Class<T> entityClass, String whereSql, Object[] queryParams) {
        String entityClassName = entityClass.getName();
        Query query = entityManager.createQuery(
                "SELECT o FROM "
                        + entityClassName
                        + " o "
                        + ((whereSql == null || whereSql.length() == 0) ? ""
                        : "WHERE " + whereSql));
        setQueryParams(query, queryParams);
        query.setHint("org.hibernate.cacheable", true);
        return query.getResultList();
    }



    @Override
    public <T extends BaseEntity> List<T> queryByWherePage (Class<T> entityClass, String whereSql, Object[] queryParams, int offset, int pageSize) {
        String entityClassName = entityClass.getName();
        Query query = entityManager.createQuery(
                "SELECT o FROM "
                        + entityClassName
                        + " o "
                        + ((whereSql == null || whereSql.length() == 0) ? ""
                        : "WHERE " + whereSql));
        setQueryParams(query, queryParams);
        query.setMaxResults(pageSize);
        query.setFirstResult(offset);

        query.setHint("org.hibernate.cacheable", true);
        return query.getResultList();
    }


    /**
     * 设置查询参数
     * @param query
     * @param queryParams
     * @return
     */
    protected static Query setQueryParams(Query query, Object queryParams) {
        if (queryParams != null) {
            if (queryParams instanceof Object[]) {
                Object[] params = (Object[]) queryParams;
                if (params.length > 0) {
                    for (int i = 0; i < params.length; i++) {
                        query.setParameter(i + 1, params[i]);
                    }
                }
            } else if (queryParams instanceof Map) {
                Map params = (Map) queryParams;
                Iterator<String> it = params.keySet().iterator();
                while(it.hasNext()){
                    String key = it.next();
                    query.setParameter(key, params.get(key));
                }
            }
        }
        return query;
    }

    /**
     * 是否存在
     * @param entityClass
     * @param whereSql
     * @param queryParams
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> boolean isExistedByWhere(Class<T> entityClass,
                                                           String whereSql, Object[] queryParams) {
        long count = getCountByWhere(entityClass, whereSql, queryParams);
        return count > 0 ? true : false;
    }

    /**
     *
     * @param entityClass
     * @param whereSql
     * @param queryParams
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> long getCountByWhere(Class<T> entityClass,
                                                   String whereSql, Object[] queryParams) {
        StringBuffer sf_QL = new StringBuffer("SELECT COUNT(1)").append("  FROM ")
                .append(entityClass.getName()).append(
                        " o WHERE 1=1 ");
        if (whereSql != null && whereSql.length() != 0) {
            sf_QL.append(" AND ").append(whereSql);
        }
        Query query = entityManager.createQuery(sf_QL.toString());
        this.setQueryParams(query, queryParams);
        return (Long) query.getSingleResult();
    }

    /**
     *
     * @param entityClass
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> long getCountByWhere(Class<T> entityClass){
        StringBuffer sf_QL = new StringBuffer("SELECT COUNT(1)").append("  FROM ")
                .append(entityClass.getName()).append(
                        " o WHERE 1=1 ");
        Query query = entityManager.createQuery(sf_QL.toString());
        return (Long)query.getSingleResult();
    }


    /**
     *
     * 用于复杂jpql查询
     *
     * @param fullJpql
     * @param queryParams
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> List<T> queryByFullJPQL (  String fullJpql, Object[] queryParams ) {

        Query query = entityManager.createQuery(fullJpql);
        setQueryParams(query, queryParams);

        query.setHint("org.hibernate.cacheable", true);
        return query.getResultList();
    }

    /**
     *
     * 用于复杂jpql查询 分页查询
     *
     * @param fullJpql
     * @param queryParams
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> List<T> queryByFullJPQLPage (String fullJpql, Object[] queryParams ,int offset,int pageSize) {

        Query query = entityManager.createQuery(fullJpql);
        setQueryParams(query, queryParams);
        query.setMaxResults(pageSize);
        query.setFirstResult(offset);
        query.setHint("org.hibernate.cacheable", true);
        return query.getResultList();
    }

    /**
     *
     * 获取条数
     *
     * @param fullJpql
     * @param queryParams
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> long getCountByFullJPQL (  String fullJpql, Object[] queryParams ) {

        Query query = entityManager.createQuery(fullJpql);
        setQueryParams(query, queryParams);

        query.setHint("org.hibernate.cacheable", true);
        return (Long) query.getSingleResult();
    }


    public <T extends BaseEntity> Integer updateByFullJPQL(String fullJpql, Object[] queryParams){
        Query query = entityManager.createQuery(fullJpql);
        setQueryParams(query, queryParams);

        query.setHint("org.hibernate.cacheable", true);
        return (Integer) query.executeUpdate();
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}
